<!DOCTYPE html>
<html lang="en"><head><title></title><script>
/**
 * Factory method to create and load a BotGuardClient instance.
 * @param options - Configuration options for the BotGuardClient.
 * @returns A promise that resolves to a loaded BotGuardClient instance.
 */
function loadBotGuard(challengeData) {
  this.vm = this[challengeData.globalName];
  this.program = challengeData.program;
  this.vmFunctions = {};
  this.syncSnapshotFunction = null;

  if (!this.vm)
    throw new Error('[BotGuardClient]: VM not found in the global object');

  if (!this.vm.a)
    throw new Error('[BotGuardClient]: Could not load program');

  const vmFunctionsCallback = function (
    asyncSnapshotFunction,
    shutdownFunction,
    passEventFunction,
    checkCameraFunction
  ) {
    this.vmFunctions = {
      asyncSnapshotFunction: asyncSnapshotFunction,
      shutdownFunction: shutdownFunction,
      passEventFunction: passEventFunction,
      checkCameraFunction: checkCameraFunction
    };
  };

  this.syncSnapshotFunction = this.vm.a(this.program, vmFunctionsCallback, true, this.userInteractionElement, function () {/** no-op */ }, [ [], [] ])[0]

  // an asynchronous function runs in the background and it will eventually call
  // `vmFunctionsCallback`, however we need to manually tell JavaScript to pass
  // control to the things running in the background by interrupting this async
  // function in any way, e.g. with a delay of 1ms. The loop is most probably not
  // needed but is there just because.
  return new Promise(function (resolve, reject) {
    i = 0
    refreshIntervalId = setInterval(function () {
      if (!!this.vmFunctions.asyncSnapshotFunction) {
        resolve(this)
        clearInterval(refreshIntervalId);
      }
      if (i >= 10000) {
        reject("asyncSnapshotFunction is null even after 10 seconds")
        clearInterval(refreshIntervalId);
      }
      i += 1;
    }, 1);
  })
}

/**
 * Takes a snapshot asynchronously.
 * @returns The snapshot result.
 * @example
 * ```ts
 * const result = await botguard.snapshot({
 *   contentBinding: {
 *     c: "a=6&a2=10&b=SZWDwKVIuixOp7Y4euGTgwckbJA&c=1729143849&d=1&t=7200&c1a=1&c6a=1&c6b=1&hh=HrMb5mRWTyxGJphDr0nW2Oxonh0_wl2BDqWuLHyeKLo",
 *     e: "ENGAGEMENT_TYPE_VIDEO_LIKE",
 *     encryptedVideoId: "P-vC09ZJcnM"
 *    }
 * });
 *
 * console.log(result);
 * ```
 */
function snapshot(args) {
  return new Promise(function (resolve, reject) {
    if (!this.vmFunctions.asyncSnapshotFunction)
      return reject(new Error('[BotGuardClient]: Async snapshot function not found'));

    this.vmFunctions.asyncSnapshotFunction(function (response) { resolve(response) }, [
      args.contentBinding,
      args.signedTimestamp,
      args.webPoSignalOutput,
      args.skipPrivacyBuffer
    ]);
  });
}

function runBotGuard(challengeData) {
  const interpreterJavascript = challengeData.interpreterJavascript.privateDoNotAccessOrElseSafeScriptWrappedValue;

  if (interpreterJavascript) {
    new Function(interpreterJavascript)();
  } else throw new Error('Could not load VM');

  const webPoSignalOutput = [];
  return loadBotGuard({
    globalName: challengeData.globalName,
    globalObj: this,
    program: challengeData.program
  }).then(function (botguard) {
    return botguard.snapshot({ webPoSignalOutput: webPoSignalOutput })
  }).then(function (botguardResponse) {
    return { webPoSignalOutput: webPoSignalOutput, botguardResponse: botguardResponse }
  })
}

function obtainPoToken(webPoSignalOutput, integrityToken, identifier) {
  const getMinter = webPoSignalOutput[0];

  if (!getMinter)
    throw new Error('PMD:Undefined');

  const mintCallback = getMinter(integrityToken);

  if (!(mintCallback instanceof Function))
    throw new Error('APF:Failed');

  const result = mintCallback(identifier);

  if (!result)
    throw new Error('YNJ:Undefined');

  if (!(result instanceof Uint8Array))
    throw new Error('ODM:Invalid');

  return result;
}
</script></head><body></body></html>
